home *** CD-ROM | disk | FTP | other *** search
- (*
- Date: 02-05-95
- From: DON PAULSEN
-
-
- This unit provides routines to manipulate individual bits
- in memory, including test, set, clear, and toggle. You may
- also count the number of bits set with NumFlagsSet, and get
- a "picture" of them with the function FlagString.
-
- All the routines are in the interface section to provide
- complete low-level control of your own data space used for
- flags. Usually the oFlags object will be most convenient.
- Just initialize the object with the number of flags required,
- and it will allocate sufficient memory on the heap and clear
- them to zero.
- *)
-
-
- UNIT DpFlags;
-
- {$A+,B-,D-,E-,F-,G-,I-,L-,N-,O-,R-,S-,V-,X-}
- {$IFDEF VER70} {$P-,Q-,T-,Y-} {$ENDIF}
-
- (*
- File(s) DPFLAGS.PAS
- Unit(s) None
- Compiler Turbo Pascal v6.0+
- Author Don Paulsen
- v1.00 Date 7-01-92
- Last Change 11-12-93
- Version 1.11
- *)
-
- { Flags are numbered from left to right (low memory to high memory),
- starting with 0, to a maximum of 65520. If the flags object isn't used,
- use the System.FillChar routine to set or clear all the flags at once.
- The memory for storing the flags can be allocated in the data segment
- or on the heap.
-
- Here are two methods for declaring an array for the flags (not needed if
- the oFlags object is used):
-
- CONST
- cMaxFlagNumber = 50;
- cNumberOfFlags = 51;
-
- VAR
- flags_A : array [0..(cMaxFlagNumber div 8)] of byte;
- flags_B : array [0..(cNumberOfFlags - 1) div 8] of byte;
-
- Note that since the first flag is flag 0, cNumberOfFlags is always 1 greater
- than cMaxFlagNumber. }
-
-
- INTERFACE
-
- PROCEDURE SetFlag (var flags; flagNum : word);
- PROCEDURE ClearFlag (var flags; flagNum : word);
- PROCEDURE ToggleFlag (var flags; flagNum : word);
- FUNCTION FlagIsSet (var flags; flagNum : word): boolean;
- FUNCTION NumFlagsSet (var flags; numFlags: word): word;
- FUNCTION FlagString (var flags; numFlags: word): string;
-
- TYPE
- tFlags = ^oFlags;
- oFlags = OBJECT
- CONSTRUCTOR Init (numberOfFlags: word);
- PROCEDURE ClearAllFlags;
- PROCEDURE SetAllFlags;
- PROCEDURE SetFlag (flagNum: word);
- PROCEDURE ClearFlag (flagNum: word);
- PROCEDURE ToggleFlag (flagNum: word);
- FUNCTION FlagIsSet (flagNum: word): boolean;
- FUNCTION NumFlagsSet : word;
- FUNCTION FlagString : string;
- DESTRUCTOR Done;
- PRIVATE
- flags : pointer;
- numFlags : word;
- END;
-
-
- IMPLEMENTATION
-
- {=======================================================}
- PROCEDURE SetFlag (var flags; flagNum: word); assembler;
-
- ASM
- les di, flags
- mov cx, flagNum
- mov bx, cx
- shr bx, 1
- shr bx, 1
- shr bx, 1
- and cl, 7
- mov al, 80h
- shr al, cl
- or es:[di][bx], al
- END;
-
- {=========================================================}
- PROCEDURE ClearFlag (var flags; flagNum: word); assembler;
-
- ASM
- les di, flags
- mov cx, flagNum
- mov bx, cx
- shr bx, 1
- shr bx, 1
- shr bx, 1
- and cl, 7
- mov al, 7Fh
- ror al, cl
- and es:[di][bx], al
- END;
-
- {==========================================================}
- PROCEDURE ToggleFlag (var flags; flagNum: word); assembler;
-
- ASM
- les di, flags
- mov cx, flagNum
- mov bx, cx
- shr bx, 1
- shr bx, 1
- shr bx, 1
- and cl, 7
- mov al, 80h
- shr al, cl
- xor es:[di][bx], al
- END;
-
- {=================================================================}
- FUNCTION FlagIsSet (var flags; flagNum: word): boolean; assembler;
-
- ASM
- les di, flags
- mov cx, flagNum
- mov bx, cx
- shr bx, 1
- shr bx, 1
- shr bx, 1
- and cl, 7
- inc cx
- mov al, es:[di][bx]
- rol al, cl
- and al, 1
- @done:
- END;
-
- {=================================================================}
- FUNCTION NumFlagsSet (var flags; numFlags: word): word; assembler;
-
- ASM
- push ds
- cld
- lds si, flags
- xor bx, bx
- mov cx, numFlags
- mov dx, cx
- xor di, di
- shr cx, 1
- shr cx, 1
- shr cx, 1
- jcxz @remainder
- @byte8:
- lodsb
- shl al, 1; adc bx, di
- shl al, 1; adc bx, di
- shl al, 1; adc bx, di
- shl al, 1; adc bx, di
- shl al, 1; adc bx, di
- shl al, 1; adc bx, di
- shl al, 1; adc bx, di
- shl al, 1; adc bx, di
- loop @byte8
- @remainder:
- mov cx, dx
- and cx, 7
- jz @done
- lodsb
- @bit:
- shl al, 1
- adc bx, di
- loop @bit
- @done:
- mov ax, bx
- pop ds
- END;
-
- {==================================================================}
- FUNCTION FlagString (var flags; numFlags: word): string; assembler;
-
- { Returns a string of 0's & 1's showing the flags. Note that at most 255
- flags can shown in a string. Returns nul if numFlags is 0 or greater
- than 255. }
-
- ASM
- push ds
- cld
- lds si, flags
- les di, @result
- mov cx, numflags
- or ch, ch
- jz @ok
- xor cx, cx
- @ok:
- mov al, cl
- stosb { length of string }
- jcxz @done
- mov dx, cx
- push dx { save number of flags }
- mov ah, '0'
- shr dl, 1
- shr dl, 1
- shr dl, 1
- jz @remainder
- @byte8: { do 8 bits at a time }
- lodsb
- mov bl, al
- mov cl, 8
- @bit8:
- mov al, ah { ah = '0' }
- shl bl, 1
- adc al, dh { dh = 0 }
- stosb
- loop @bit8
- dec dl
- jnz @byte8
-
- @remainder: { do remaining (numFlags mod 8) bits }
- pop dx
- mov cx, dx
- and cl, 7 { 0 <= cx <= 7 (number of flags in partial byte) }
- jz @done
- lodsb { last byte containing flags }
- mov bl, al
- @bit:
- mov al, ah { ah = '0' }
- shl bl, 1
- adc al, dh { dh = 0 }
- stosb
- loop @bit
- @done:
- pop ds
- END;
-
- {=============================================}
- CONSTRUCTOR oFlags.Init (numberOfFlags: word);
-
- BEGIN
- if numberOfFlags > 65520 then FAIL;
- numFlags:= numberOfFlags;
- GetMem (flags, (numFlags + 7) div 8);
- if flags = nil then FAIL;
- END;
-
- {==============================}
- PROCEDURE oFlags.ClearAllFlags;
-
- BEGIN
- FillChar (flags^, (numFlags + 7) div 8, #0);
- END;
-
- {============================}
- PROCEDURE oFlags.SetAllFlags;
-
- BEGIN
- FillChar (flags^, (numFlags + 7) div 8, #1);
- END;
-
- {========================================}
- PROCEDURE oFlags.SetFlag (flagNum: word);
-
- BEGIN
- DpFlags.SetFlag (flags^, flagNum);
- END;
-
- {==========================================}
- PROCEDURE oFlags.ClearFlag (flagNum: word);
-
- BEGIN
- DpFlags.ClearFlag (flags^, flagNum);
- END;
-
- {===========================================}
- PROCEDURE oFlags.ToggleFlag (flagNum: word);
-
- BEGIN
- DpFlags.ToggleFlag (flags^, flagNum);
- END;
-
- {==================================================}
- FUNCTION oFlags.FlagIsSet (flagNum: word): boolean;
-
- BEGIN
- FlagIsSet:= DpFlags.FlagIsSet (flags^, flagNum);
- END;
-
- {=================================}
- FUNCTION oFlags.NumFlagsSet: word;
-
- BEGIN
- NumFlagsSet:= DpFlags.NumFlagsSet (flags^, numFlags);
- END;
-
- {==================================}
- FUNCTION oFlags.FlagString: string;
-
- VAR
- w : word;
-
- BEGIN
- w:= numFlags;
- if w > 255 then w:= 255;
- FlagString:= DpFlags.FlagString (flags^, w);
- END;
-
- {======================}
- DESTRUCTOR oFlags.Done;
-
- BEGIN
- if flags <> nil then FreeMem (flags, (numFlags + 7) div 8);
- END;
-
- END. { Unit DpFlags }
-